﻿using System;
using G.Model;
using System.Collections.Generic;

namespace G.Runtime
{
    
    public class CalcGameValues : GameValues
    {
        private GamePlayer _Player;
        
        internal CalcGameValues(GameValueDefs pGameValueDefs,
                                GameSpace pGame,
                                GamePlayer pPlayer)
            : base()
        {
            _GameValueDefs = pGameValueDefs;
            _Player = pPlayer;
            _Player.Game.Elements.ElementAddedEvent += OnElementChangedEvent;
            _Player.Game.Elements.ElementRemovedEvent += OnElementChangedEvent;
            _Player.Game.Elements.PlayerChangingEvent += OnPlayerChangingEvent;
            Sync();
        }
        
        private void OnChangedEvent(GameElement subject)
        {
            Sync();
        }
        
        private void OnPlayerChangingEvent(GameElement subject)
        {
            Sync();
        }
        
        private void OnElementChangedEvent(GameElement subject)
        {
            Sync();
        }
        
        private void OnChangedEvent(GameValue var)
        {
            FireChangedEvent();
        }
        
        private void Sync()
        {
            SyncValues(new GameValues(_GameValueDefs));
            foreach(GameElement e in this._Player.Game.Elements)
            {
                if (e.Player != this._Player.Name)
                {
                    continue;
                }
                
                SyncValues(e.GameValues);
            }
            
//            List<GameValue> remove = new List<GameValue>();
//            foreach(GameValue v in this)
//            {
//                bool found = false;
//                foreach(GameElement e in this._Player.Game.Elements)
//                {
//                    foreach(GameValue test in e.GameValues)
//                    {
//                        if (this.Contains(test))
//                        {
//                            found = true;
//                            break;
//                        }
//                    }
//                }
//                
//                if (!found)
//                {
//                    remove.Add(v);
//                }
//            }
//            
//            foreach(GameValue v in remove)
//            {
//                base.Remove(v);
//            }
        }



        void SyncValues(GameValues gameValues)
        {
            foreach (GameValue v in gameValues) {
                if (v.GetType() != typeof(IntGameValue)) {
                    continue;
                }
                IntGameValue i = (IntGameValue)v;
                if (!this.Contains(v)) {
                    CalcIntGameValue calc = new CalcIntGameValue(i.Def, _Player);
                    this.Add(calc);
                } else {
                    CalcIntGameValue current = (CalcIntGameValue)(this[v.Def.Name]);
                    current.SyncElements();
                }
            }
        }
        
        protected override void InsertItem(int index, GameValue item)
        {
            base.InsertItem(index, item);
            item.ChangedEvent += OnChangedEvent;
        }
        
        protected override void RemoveItem(int index)
        {
            GameValue item = this[index];
            base.RemoveItem(index);
            item.ChangedEvent -= OnChangedEvent;
        }
        
    }
    
}
